#pragma once
#include <datasource/EmptyCamera.h>
#include <opencv2/core.hpp>
#include <QByteArray>
#include <QList>


const int WIDTH = 64;
const int HEIGHT = 8;
const int FRAME_MAX_SIZE = 64;
const int BLOCK_HEAD_SIZE = 6;
const int CANFD_HEAD_SIZE = 3;
const int BLOCK_MAX_DATA_SIZE = FRAME_MAX_SIZE - BLOCK_HEAD_SIZE;
const int RAW_ROW_SIZE = WIDTH << 2;
const int ROW_LAST_BLOCK = 4; //ceil(RAW_ROW_SIZE / BLOCK_MAX_DATA_SIZE);
const int ROW_BLOCK_COUNT = ROW_LAST_BLOCK + 1;
const int FRAME_BLOCK_COUNT = HEIGHT*ROW_BLOCK_COUNT;

// Customized data structures to receive data
class FrameData
{
public:
    FrameData(){frame = 0;}
    void renew(int f);                  // Clear the data and receive the next frame
    bool isCompleted(int *block_count); // Check whether a complete frame has been received

  public:
    uint32_t frame;                      // The sequence number of a frame
    uint8_t rows[HEIGHT];                // The row number of a frame data
    uint8_t blocks[FRAME_BLOCK_COUNT];         // The interline number of a row data
    uint8_t rawdata[WIDTH * HEIGHT * 4]; // The data of a frame
    int block_count;                     // The canfd data pack count of a frame
};

class MySerialPreview
{
public:
    explicit MySerialPreview();
private:
    FrameData currentData; 
    bool is_working;

    // ------------------- Parameters and function definations for preview -------------------
    wy6005param_t *wy6005param;
    std::shared_ptr<open3d::geometry::PointCloud> cloud_ptr;
    virtual void showRGBToUI(cv::Mat img) = 0;
    virtual void showDepthToUI(cv::Mat img) = 0;
    virtual void showBoxToUI(CvtBox box) = 0;
    virtual void showFPSToUI(int val) = 0;
    virtual void DevIdChanged(int val) = 0;

    // ------------------- Process a canfd pack -------------------
    int appendPack(QByteArray &data, int data_len, FrameData &frameData);

protected:
    // ------------------- Parameters and function definations for preview -------------------
    EmptyCamera *cxx_camera = nullptr;

    bool is_first = true;
    void consumerStop();
    void consumerStart(wy6005param_t *para);
    bool consumerInit();
    void displayFrame(FrameData &data);

    // ------------------- Process the receiving data -------------------
    void dataArrived(QByteArray &data, QByteArray &partialdata);
};

